<?php
require "Right.php";

class Rights implements Iterator
{
	protected $_rights;
	
	
	public function __construct()
	{
		$this->_rights = array();
	}
	
	/**
	 * Creates a new right within the rights system, 
	 * returns either the new right or false on a error.
	 *
	 * @param string $handle 
	 * @param string $name   
	 * @return Right 	
	 */
	protected function addRight($handle, $name)
	{
		if (! is_string($handle) ) return false;
		if (! is_string($name) ) return false;

		$right = new Right($handle, $name);
		$this->_rights[$handle] = $right;

		return $right;
	}
	
	/**
	 * Loads the rights from a xml file
	 *
	 * @param string $xmlfile
	 */
	public function load($xmlfile)
	{
		$xml = simplexml_load_file($xmlfile);

		foreach($xml->right as $xmlright){
			$right = $this->addRight((string)($xmlright['handle']), (string)($xmlright['friendly']));
			$right->description = $xmlright->description;
			foreach($xmlright->allows->allow as $xmlallow) {
				
				// Grab the values
				$module = (string)($xmlallow['module']);
				$controller = (string)($xmlallow['controller']);
				$action = (string)($xmlallow['action']);
				
				// Skip any malformed rights
				if ($module=="" || $controller=="" || $action=="") {
					throw new Exception("Malformed allow for '" . $right->handle . "': all attributes must be non-empty.");
				}
				
				// Translate stars into null values
				if ($module=="*") $module = null;
				if ($controller=="*") $controller = null;
				if ($action=="*") $action = null;
				
				// Acl limitation: a resource is a single name
				// So it must be either module/controller or */*
				if ((!$module && $controller) || ($module && !$controller)) {
					throw new Exception("Malformed allow for '" . $right->handle . "': module and controller must be both * or both set (ACL conformity).");
				}
				
				$right->allow($module, $controller, $action);
			}
		}
	}
	
	/**
	 * Get a right, if it is defined
	 * Otherwise it will return null
	 *
	 * @param string $handle
	 * @return Right
	 */
	public function getRight($handle)
	{
		if (array_key_exists($handle, $this->_rights)) 
			return $this->_rights[$handle];
		else 
			return null;
	}
	
	public function dump()
	{
		echo "<table>";
		foreach($this->_rights as $handle=>$right){
			echo "<tr><th>".$right->handle."</th><tr>";
			foreach($right->allows as $right) {
				echo "<tr><td>" . $right['module']." / ".$right['controller']." / ".$right['action']."</td></tr>";
			}
		}
		echo "</table>";
	}
	
	/**
	 * Here for easy utilizing of the rights object
	 *
	 * @param unknown_type $object
	 * @return Rights
	 */
	public static function cast(Rights $object)  
	{
		return $object;
	}
	

    public function rewind() {
        reset($this->_rights);
    }

    public function current() {
        $var = current($this->_rights);
        return $var;
    }

    public function key() {
        $var = key($this->_rights);
        return $var;
    }

    public function next() {
        $var = next($this->_rights);
        return $var;
    }

    public function valid() {
        $var = $this->current() !== false;
        return $var;
    }
    
	public function toArray()
	{	
		return $this->_rights;
	}
	
}

